#include "Server.h"

using namespace car;

bool Server::mIsRunning;
bool Server::mIsShutDown;

Server::Server(void)
{
	this->clearRoomList();
	this->clearPlayerList();
	mIsRunning = false;
	mIsShutDown = true;
}


Server::~Server(void)
{
	this->clearRoomList();
	this->clearPlayerList();
	mIsRunning = false;
	mIsShutDown = true;
}

bool Server::startServer()
{
	mSessionMgr.startSession();
	if( mIsShutDown && !mIsRunning )
	{
		mThreadHandle = CreateThread( NULL, 0, serverThread, (LPVOID)this, 0, &mThreadId );
		if( mThreadHandle )
		{
			mIsShutDown = false;
			mIsRunning = true;
			return true;
		}
	}
	return false;
}

void Server::stopServer()
{
	mIsRunning = false;
	while( !mIsShutDown )
		Sleep( 1 );
	mSessionMgr.stopSession();
	mPlayerList.clear();
	mRoomList.clear();
}

Player * Server::getPlayer( unsigned int playerId )
{
	for( std::list<Player *>::iterator itr = mPlayerList.begin(); itr != mPlayerList.end(); ++itr )
	{
		Player * player = ( *itr );
		if( player && player->getPlayerId() == playerId )
		{
			return player;
		}
	}

	return NULL;
}

void Server::addPlayer( Player * player )
{
	if( !player || hasPlayer( player->getPlayerId() ) )
		return;
	mPlayerList.push_back( player );
}

void Server::removePlayer( unsigned int playerId )
{
	for( std::list<Player *>::iterator itr = mPlayerList.begin(); itr != mPlayerList.end(); ++itr )
	{
		Player * player = ( *itr );

		if( player && player->getPlayerId() == playerId )
		{
			if( player->getRoomId() != 0 )
			{
				getRoom( player->getRoomId() )->removePlayer( playerId );
			}
			delete player;
			mPlayerList.erase( itr );
			break;
		}
	}
}

void Server::clearPlayerList()
{
	for( std::list<Player *>::iterator itr = mPlayerList.begin(); itr != mPlayerList.end(); ++itr )
	{
		Player * player = ( *itr );
		if( player )
		{
			if( player->getRoomId() != 0 )
			{
				getRoom( player->getRoomId() )->removePlayer( player->getPlayerId() );
			}
			delete player;
			player = NULL;
		}
	}
	mPlayerList.clear();
}

bool Server::hasPlayer( unsigned int playerId )
{
	for( std::list<Player *>::iterator itr = mPlayerList.begin(); itr != mPlayerList.end(); ++itr )
	{
		Player * player = ( *itr );
		if( player && player->getPlayerId() == playerId )
		{
			return true;
		}
	}

	return false;
}

Room * Server::getRoom( unsigned int roomId )
{
	for( std::list<Room *>::iterator itr = mRoomList.begin(); itr != mRoomList.end(); ++itr )
	{
		Room * room = ( *itr );
		if( room && room->getRoomId() == roomId )
		{
			return ( *itr );
		}
	}

	return NULL;
}

void Server::removeRoom( unsigned int roomId )
{
	for( std::list<Room *>::iterator itr = mRoomList.begin(); itr != mRoomList.end(); ++itr )
	{
		Room * room = ( *itr );
		if( room && room->getRoomId() == roomId )
		{
			delete room;
			room = NULL;
			mRoomList.erase( itr );
			break;
		}
	}
}

void Server::addRoom( Room * room )
{
	if( room )
		mRoomList.push_back( room );
}

bool Server::hasRoom( unsigned int roomId )
{
	for( std::list<Room *>::iterator itr = mRoomList.begin(); itr != mRoomList.end(); ++itr )
	{
		Room * room = ( *itr );
		if( room && room->getRoomId() == roomId )
		{
			return true;
		}
	}

	return false;
}

void Server::clearRoomList()
{
	for( std::list<Room *>::iterator itr = mRoomList.begin(); itr != mRoomList.end(); ++itr )
	{
		Room * room = ( *itr );
		if( room )
		{
			delete room;
			room = NULL;
		}
	}
	mRoomList.clear();
}

unsigned int Server::generatePlayerId( char name[], int nameSize, char pwd[], int pwdSize )
{
	for( std::list<Player *>::iterator itr = mPlayerList.begin(); itr != mPlayerList.end(); ++itr )
	{
		Player * player = ( *itr );
		if( player )
		{
			char playerName[kMaxPlayerNameLength];
			unsigned int playerNameSize;
			( *itr )->getPlayerName( playerName, &playerNameSize );
			if( playerNameSize == nameSize && strcmp( name, playerName ) )
			{
				return ( *itr )->getPlayerId();
			}
		}
	}
	return mPlayerList.size() + 1;
}

unsigned int Server::generateRoomId() {
	return mRoomList.size() + 1;
}

void Server::update( float deltaTime ) {
	mSessionMgr.update( deltaTime );
}

DWORD WINAPI Server::serverThread( LPVOID param )
{
	Server * server = ( Server * )param;
	while( mIsRunning )
	{
		static DWORD prevTime = GetTickCount();
		DWORD currentTime = GetTickCount();
		DWORD dwDuration = currentTime - prevTime;
		float duration = ( float )( dwDuration ) / 1000;
		if( duration > 0 )
		{
			server->update( duration );
		}
		prevTime = currentTime;
		if( dwDuration > 0 && dwDuration < 33 )
			Sleep( 33 - dwDuration );
	}
	mIsShutDown = true;

	return 0;
}
